//
//  MaineJournalAppDelegate.h
//  MaineJournal
//
//  Created by Administrator on 8/15/11.
//  Copyright 2011 University of Maine. All rights reserved.
//

#import <QuartzCore/QuartzCore.h>
#if TARGET_IPHONE_SIMULATOR
#import <unistd.h>
#endif

#import "ReaderViewController.h"
#import "ZoomView.h"
#import "MiniZip.h"
#import "UnRAR.h"
#import "ImageUtilities.h"
#import "Logging.h"

#define kMaxPageSize 1500.0
#define kLeftZoneRatio 0.2
#define kRightZoneRatio 0.8

@interface ComicPageView : ZoomView {
@private
    NSString* _file;
}
@property(nonatomic, copy) NSString* file;
- (id) initWithTapTarget:(id)target action:(SEL)action;
- (void) displayImage:(UIImage*)anImage;
@end

@implementation ComicPageView

@synthesize file=_file;

- (id) initWithTapTarget:(id)target action:(SEL)action {
    
    //// test ...
    if ((self = [super init])) {
        self.alwaysBounceHorizontal = NO;
        self.alwaysBounceVertical = NO;
        
        UITapGestureRecognizer* recognizer = [[UITapGestureRecognizer alloc] initWithTarget:target action:action];
        [recognizer requireGestureRecognizerToFail:[[self gestureRecognizers] lastObject]];
        [self addGestureRecognizer:recognizer];
        [recognizer release];
    }
    return self;
}

- (void) displayImage:(UIImage*)anImage {
    if (anImage) {
        UIImageView* imageView = [[UIImageView alloc] initWithImage:anImage];
        [self setDisplayView:imageView];
        [imageView release];
    } else {
        [self setDisplayView:nil];
    }
}

- (void) dealloc {
    [_file release];
    [super dealloc];
}

@end

@implementation ReaderViewController

@synthesize navigationBar=_navigationBar, navigationControl=_navigationControl, contentView=_contentView;
@synthesize menuViewInReader = _menuViewInReader;
@synthesize modelViewInReader = _modelViewInReader;

//@synthesize buttonView = _buttonView;

- (id) initWithComic:(Comic*)comic {
    DCHECK(comic.sqlRowID);
    if ((self = [super init])) {
        _comic = [comic retain];
        
        NSString* path = [LibraryConnection libraryRootPath];
        if (comic.collection) {
            Collection* collection = [[LibraryConnection mainConnection] fetchObjectOfClass:[Collection class]
                                                                               withSQLRowID:_comic.collection];
            path = [path stringByAppendingPathComponent:collection.name];
        }
        _path = [[path stringByAppendingPathComponent:_comic.name] copy];
        
        if ([[NSFileManager defaultManager] fileExistsAtPath:_path]) {
            NSString* extension = [_path pathExtension];
            if (![extension caseInsensitiveCompare:@"pdf"]) {
                _type = kComicType_PDF;
                CGPDFDocumentRef document = CGPDFDocumentCreateWithURL((CFURLRef)[NSURL fileURLWithPath:_path]);
                if (document) {
                    _contents = [[NSNumber alloc] initWithInteger:CGPDFDocumentGetNumberOfPages(document)];
                    CGPDFDocumentRelease(document);
                }
            } else if (![extension caseInsensitiveCompare:@"zip"] || ![extension caseInsensitiveCompare:@"cbz"]) {
                _type = kComicType_ZIP;
                _contents = [[MiniZip alloc] initWithArchiveAtPath:_path];
            } else if (![extension caseInsensitiveCompare:@"rar"] || ![extension caseInsensitiveCompare:@"cbr"]) {
                _type = kComicType_RAR;
                _contents = [[UnRAR alloc] initWithArchiveAtPath:_path];
            }
        }
        if (!_contents) {
            LOG_ERROR(@"Failed loading comic at \"%@\"", path);
            [self release];
            return nil;
        }
        
        self.wantsFullScreenLayout = YES;
    }
    return self;
}

- (void) dealloc {
    [_navigationBar release];
    [_navigationControl release];
    [_contentView release];
    
    [_pageLabel release];
    [_documentView release];
    [_contents release];
    [_path release];
    [_comic release];
    
    [_titleLabel release];
    [_pageOfLabel release];
    [super dealloc];
}

- (void) saveState {
    NSInteger status = (_documentView.selectedPageIndex < _documentView.pageViews.count - 1 ? _documentView.selectedPageIndex : 0);
    if (status != _comic.status) {
        _comic.status = status;
        [[LibraryConnection mainConnection] updateObject:_comic];
    }
}

- (BOOL) navigationBar:(UINavigationBar*)navigationBar shouldPopItem:(UINavigationItem*)item {
    [self.parentViewController dismissModalViewControllerAnimated:YES];
    return YES;
}

- (void) documentView:(DocumentView*)documentView willShowPageView:(UIView*)view {
    CGImageRef imageRef = NULL;
    if (_type == kComicType_PDF) {
        CGPDFDocumentRef document = CGPDFDocumentCreateWithURL((CFURLRef)[NSURL fileURLWithPath:_path]);  // Don't keep CGPDFDocument around as it caches pages content heavily
        if (document) {
            CGPDFPageRef page = CGPDFDocumentGetPage(document, view.tag);
            if (page) {
                imageRef = CreateRenderedPDFPage(page, CGSizeMake(kMaxPageSize, kMaxPageSize), kImageScalingMode_AspectFit,
                                                 [[UIColor whiteColor] CGColor]);
                LOG_VERBOSE(@"Loading page %i of %ix%i pixels resized to %ix%i pixels", view.tag,
                            (int)CGPDFPageGetBoxRect(page, kCGPDFMediaBox).size.width, (int)CGPDFPageGetBoxRect(page, kCGPDFMediaBox).size.height,
                            CGImageGetWidth(imageRef), CGImageGetHeight(imageRef));
                
                //set the number of current page
                _pageOfLabel.text = [[NSNumber numberWithInt:view.tag] stringValue] ;
            }
            CGPDFDocumentRelease(document);
        }
    } else {
        NSString* temp = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]];
        if ([_contents extractFile:[(ComicPageView*)view file] toPath:temp]) {
            NSData* data = [[NSData alloc] initWithContentsOfFile:temp];
            if (data) {
                UIImage* image = [[UIImage alloc] initWithData:data];
                if (image) {
                    imageRef = [image CGImage];
                    if ((CGImageGetWidth(imageRef) > kMaxPageSize) || (CGImageGetHeight(imageRef) > kMaxPageSize)) {
                        imageRef = CreateScaledImage(imageRef, CGSizeMake(kMaxPageSize, kMaxPageSize), kImageScalingMode_AspectFit,
                                                     [[UIColor blackColor] CGColor]);
                    } else {
                        CGImageRetain(imageRef);
                    }
                    LOG_VERBOSE(@"Loading page %i of %ix%i pixels resized to %ix%i pixels", view.tag,
                                (int)image.size.width, (int)image.size.height, CGImageGetWidth(imageRef), CGImageGetHeight(imageRef));
                    [image release];
                }
                [data release];
            }
            [[NSFileManager defaultManager] removeItemAtPath:temp error:NULL];
        }
    }
    if (imageRef) {
        UIImage* image = [[UIImage alloc] initWithCGImage:imageRef];
        [(ComicPageView*)view displayImage:image];
        [image release];
        view.backgroundColor = [UIColor blackColor];
        CGImageRelease(imageRef);
    } else {
        view.backgroundColor = [UIColor redColor];
    }
#if TARGET_IPHONE_SIMULATOR
    usleep(250 * 1000);
#endif
}

- (void) documentView:(DocumentView*)documentView didHidePageView:(UIView*)view {
    [(ComicPageView*)view displayImage:nil];
    view.backgroundColor = nil;
}

- (void) documentViewDidReachFirstPage:(DocumentView*)documentView {
    [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationFade];
    
    [self.parentViewController dismissModalViewControllerAnimated:YES];
}

- (void) documentViewDidReachLastPage:(DocumentView*)documentView {
    [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationFade];
    
    [self.parentViewController dismissModalViewControllerAnimated:YES];
}

- (void) viewDidLoad {
    [super viewDidLoad];
    
    // set the title with the file name;
    //  UINavigationItem* item = [[UINavigationItem alloc] initWithTitle:[_path lastPathComponent]];
    
    UINavigationItem* item = [[UINavigationItem alloc] initWithTitle:@""];
    [_navigationBar pushNavigationItem:item animated:NO];
    _navigationBar.tintColor=[UIColor clearColor];
    [item release];
    _navigationBar.hidden = YES;
    _navigationControl.delegate = self;
    _navigationControl.continuous = NO;
    _navigationControl.margins = UIEdgeInsetsMake(0, 80, 20, 80);
    _navigationControl.thumbTintColor = [UIColor colorWithRed:0.8 green:0.8 blue:0.8 alpha:1.0];
    _navigationControl.overlayTintColor = [UIColor colorWithRed:0.7 green:0.7 blue:0.7 alpha:1.0];
    _navigationControl.hidden = YES;
    _contentView.backgroundColor = nil;
    
    _documentView = [[DocumentView alloc] initWithFrame:_contentView.bounds];
    _documentView.delegate = self;
    _documentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    [_contentView addSubview:_documentView];
    
    _pageLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 140, 20)];
    _pageLabel.font = [UIFont boldSystemFontOfSize:18];
    _pageLabel.textColor = [UIColor whiteColor];
    _pageLabel.textAlignment = UITextAlignmentCenter;
    _pageLabel.backgroundColor = nil;
    _pageLabel.opaque = NO;
    
    //    UIBarButtonItem *test = [[UIBarButtonItem alloc] initWithCustomView:_buttonView];
    
    // create a toolbar to have two buttons in the right
    UIToolbar* tools = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 640, 44)];
    tools.barStyle = UIBarStyleBlackTranslucent;
    tools.tintColor=[UIColor clearColor];
    // create the array to hold the buttons, which then gets added to the toolbar
    NSMutableArray* buttons = [[NSMutableArray alloc] initWithCapacity:3];
    
    // create a fonts button
    UIBarButtonItem* bi = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"FontsAction.png"]style:UIBarButtonItemStyleBordered target:self action:@selector(_fontsMenu:)];
//    bi.style = UIBarButtonItemStyleBordered;
    [buttons addObject:bi];
    [bi release];
    
    // create a spacer
    bi = [[UIBarButtonItem alloc]
          initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
    [buttons addObject:bi];
    [bi release];
    
    // create a search button
    bi = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"SearchAction.png"]style:UIBarButtonItemStyleBordered target:self action:@selector(_searchMenu:)];
//    bi.style = UIBarButtonItemStyleBordered;
    [buttons addObject:bi];
    [bi release];
    
    // create a spacer
    bi = [[UIBarButtonItem alloc]
          initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
    [buttons addObject:bi];
    [bi release];
    
    // create a flip effect button
    bi = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"FlipEffectAction.png"]style:UIBarButtonItemStyleBordered target:self action:@selector(_flipEffectMenu:)];
//    bi.style = UIBarButtonItemStyleBordered;
    [buttons addObject:bi];
    [bi release];
    
    // create a spacer
    bi = [[UIBarButtonItem alloc]
          initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
    [buttons addObject:bi];
    [bi release];
    
    // create a editBookmark button
    bi = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"BookmarkAction.png"]style:UIBarButtonItemStyleBordered target:self action:@selector(_bookMarksMenu:)];
//    bi.style = UIBarButtonItemStyleBordered;
    [buttons addObject:bi];
    [bi release];
    
    // create a spacer
    bi = [[UIBarButtonItem alloc]
          initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
    [buttons addObject:bi];
    [bi release];
    
    // create a information button
    bi = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"InformationAction.png"]style:UIBarButtonItemStyleBordered target:self action:@selector(_toggleMenu:)];
//    bi.style = UIBarButtonItemStyleBordered;
    [buttons addObject:bi];
    [bi release];
    
    // stick the buttons in the toolbar
    [tools setItems:buttons animated:NO];
    
    [buttons release];
    
    //popover view and menu view 
    UIViewController* modelViewController = [[UIViewController alloc] init];
    modelViewController.view = _modelViewInReader;
    _modelControllerInReader = [[UIPopoverController alloc] initWithContentViewController:modelViewController];
    _modelControllerInReader.popoverContentSize = _modelViewInReader.frame.size;
    [modelViewController release];
    
    UIViewController* menuViewController = [[UIViewController alloc ] init];
    menuViewController.view = _menuViewInReader;
    _menuControllerInReader = [[UIPopoverController alloc] initWithContentViewController:menuViewController];
    _menuControllerInReader.popoverContentSize = _menuViewInReader.frame.size;
    [menuViewController release];
    
    // and put the toolbar in the nav bar
    item.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:tools];
    [tools release];
    
    // set title in the menuView
    _titleLabel.text = [_path lastPathComponent];
}

- (void) viewDidUnload {
    
    [_titleLabel release];
    _titleLabel = nil;
    [_pageOfLabel release];
    _pageOfLabel = nil;
    [super viewDidUnload];
    
    [_pageLabel release];
    [_documentView release];
    
    self.navigationBar = nil;
    self.navigationControl = nil;
    self.contentView = nil;
}

- (void) _tapAction:(UITapGestureRecognizer*)recognizer {
    if (recognizer.state == UIGestureRecognizerStateEnded) {
        CGRect bounds = recognizer.view.bounds;
        CGPoint location = [recognizer locationInView:recognizer.view];
        // Left margin
        if (location.x <= bounds.size.width * kLeftZoneRatio) {
            [_documentView goToPreviousPage:NO];
        }
        // Right margin
        else if (location.x >= bounds.size.width * kRightZoneRatio) {
            [_documentView goToNextPage:NO];
        }
        // Center
        else {
            if ([[UIApplication sharedApplication] isStatusBarHidden]) {
                [[UIApplication sharedApplication] setStatusBarHidden:NO];
                _navigationBar.hidden = NO;
                _navigationControl.hidden = NO;
            } else {
                [[UIApplication sharedApplication] setStatusBarHidden:YES];
                _navigationBar.hidden = YES;
                _navigationControl.hidden = YES;
            }
        }
    }
}

- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    
    NSMutableArray* array = [[NSMutableArray alloc] init];
    if (_type == kComicType_PDF) {
        NSUInteger count = [(NSNumber*)_contents integerValue];
        for (NSUInteger i = 0; i < count; ++i) {
            ComicPageView* view = [[ComicPageView alloc] initWithTapTarget:self action:@selector(_tapAction:)];
            view.tag = i + 1;
            [array addObject:view];
            [view release];
        }
    } else {
        [_contents setSkipInvisibleFiles:YES];
        NSUInteger index = 0;
        for (NSString* file in [[_contents retrieveFileList] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]) {
            NSString* extension = [file pathExtension];
            if (![extension caseInsensitiveCompare:@"jpg"] || ![extension caseInsensitiveCompare:@"jpeg"] ||
                ![extension caseInsensitiveCompare:@"png"] || ![extension caseInsensitiveCompare:@"gif"]) {
                ComicPageView* view = [[ComicPageView alloc] initWithTapTarget:self action:@selector(_tapAction:)];
                view.tag = ++index;
                view.file = file;
                [array addObject:view];
                [view release];
            }
        }
    }
    [_documentView setPageViews:array initialPageIndex:MAX(_comic.status, 0)];
    _navigationControl.numberOfPages = array.count;
    _navigationControl.numberOfMarkers = MIN(array.count, 50);
    _navigationControl.currentPage = _documentView.selectedPageIndex;
    [array release];
    
    [[UIApplication sharedApplication] setStatusBarHidden:YES
                                            withAnimation:(animated ? UIStatusBarAnimationFade : UIStatusBarAnimationNone)];
}

- (void) viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    
    [self saveState];
}

- (void) viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    
    _documentView.pageViews = nil;
}

- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return YES;
}

- (void) documentViewDidChangePage:(DocumentView*)documentView {
    _navigationControl.currentPage = _documentView.selectedPageIndex;
}

- (UIView*) navigationControlOverlayViewForCurrentPage:(NavigationControl*)control {
    _pageLabel.text = [NSString stringWithFormat:NSLocalizedString(@"LABEL_FORMAT", nil), _navigationControl.currentPage + 1,
                       _navigationControl.numberOfPages];
    return _pageLabel;
}

- (IBAction) selectPage:(id)sender {
    _documentView.selectedPageIndex = _navigationControl.currentPage;
}

// popover view and actions
- (void) _fontsMenu:(id)sender {
    if (_modelControllerInReader.popoverVisible) {
        [_modelControllerInReader dismissPopoverAnimated:YES];
    } else {
        [_modelControllerInReader presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
    }
}

- (void) _searchMenu:(id)sender {
    if (_modelControllerInReader.popoverVisible) {
        [_modelControllerInReader dismissPopoverAnimated:YES];
    } else {
        [_modelControllerInReader presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
    }
}

- (void) _flipEffectMenu:(id)sender {
    if (_modelControllerInReader.popoverVisible) {
        [_modelControllerInReader dismissPopoverAnimated:YES];
    } else {
        [_modelControllerInReader presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
    }
}

- (void) _bookMarksMenu:(id)sender {
    if (_modelControllerInReader.popoverVisible) {
        [_modelControllerInReader dismissPopoverAnimated:YES];
    } else {
        [_modelControllerInReader presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
    }
}

- (void) _toggleMenu:(id)sender {
    NSLog(@"menu :(");
    if (_menuControllerInReader.popoverVisible) {
        [_menuControllerInReader dismissPopoverAnimated:YES];
    } else {
        [_menuControllerInReader presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
    }
}

@end
